﻿/************************************************************************

   Extended Silverlight Toolkit

   Copyright (C) 2010-2012 Xceed Software Inc.

   This program is provided to you under the terms of the Microsoft Public
   License (Ms-PL) as published at http://extendedsilverlight.codeplex.com/license

   Please purchase a commercial version of this toolkit if you are using
   it in a commercial product. The commercial versions support the project,
   and also include more features for each control, priority support,
   source code, updates, removed watermark, and a proprietary license.

   Visit http://xceed.com and follow @datagrid on Twitter.

  **********************************************************************/

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace Xceed.Silverlight.Data
{
  internal class CurrentEnumerator<T> : AsyncParentEnumerator<T>
  {
    private static Guid ResetCallId = DataUtils.CreateCallId();

    public CurrentEnumerator( IAsyncEnumerator<T> childEnumerator )
      : base( childEnumerator )
    {
    }

    public IAsyncEnumerator<T> CurrentEnumeratorChild
    {
      get
      {
        return this.ChildEnumeratorTyped;
      }
    }

    public IMoveAndFetchAsyncResult BeginMoveAndFetch( int expectedMoveCount, int expectedFetchCount, AsyncCallback userCallback, object asyncState )
    {
      return this.BeginJumpMoveAndFetch( new JumpMoveAndFetchParameters( m_currentPosition, expectedMoveCount, expectedFetchCount ), userCallback, asyncState );
    }

    public MoveAndFetchResult<T> EndMoveAndFetch( IMoveAndFetchAsyncResult moveAndFetchAsyncResult )
    {
      JumpMoveAndFetchResult<T> result = this.EndJumpMoveAndFetch( ( JumpMoveAndFetchAsyncResult )moveAndFetchAsyncResult );
      m_currentPosition = result.EndPositionObject;
      return new MoveAndFetchResult<T>( 
                   result.ActualMoveCount, 
                   result.FetchedItems, 
                   result.ApproximateMove,
                   result.ExpectedMoveCount, 
                   result.ExpectedFetchCount, 
                   result.Result,
                   result.EndPositionOffset,
                   result.TotalCount );
    }

    public IAsyncResult BeginReset( AsyncCallback userCallback, object asyncState )
    {
      AsyncResult asyncResult = new AsyncResult( CurrentEnumerator<T>.ResetCallId, userCallback, asyncState );
      asyncResult.StartSync( new ResetResult() );
      return asyncResult;
    }

    public ResetResult EndReset( IAsyncResult resetAsyncResult )
    {
      resetAsyncResult.ValidateCallEnd( CurrentEnumerator<T>.ResetCallId );
      m_currentPosition = SourcePosition.BeforeFirst;
      return resetAsyncResult.GetCallResult<ResetResult>();
    }

    protected override void ChildDataChanged( DataChangedEventArgs args )
    {
      if( args.Action == DataChangedAction.Replace )
      {
        if( m_currentPosition is ItemPosition )
        {
          if( object.Equals( args.OldItem, ( ( ItemPosition )m_currentPosition ).Item ) )
          {
            m_currentPosition = new ItemPosition( args.NewItem );
          }
        }
      }
      else if( args.Action == DataChangedAction.Remove )
      {
        object removed = args.OldItem;
        SourcePosition newCurrentPosition = null;

        if( m_currentPosition is ItemPosition )
        {
          object currentItem = ( ( ItemPosition )m_currentPosition ).Item;
          if( object.Equals( currentItem, removed ) )
          {
            if( args.RemovePosition != null )
            {
              m_currentPosition = args.RemovePosition;
              newCurrentPosition = m_currentPosition;
            }
          }
        }
        if( newCurrentPosition != null )
        {
          args = new DataChangedEventArgs( DataChangedAction.Remove, args.OldItem, args.RemovePosition, newCurrentPosition );
        }
      }
      base.ChildDataChanged( args );
    }

    private SourcePosition m_currentPosition = SourcePosition.BeforeFirst;

  }
}
